package com.google.gwt.it2tool.client.widget;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeSet;

import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.it2tool.client.CustomFactoryOrder;
import com.google.gwt.it2tool.client.Factory;
import com.google.gwt.it2tool.client.FactorySorter;
import com.google.gwt.it2tool.client.FactorySorter.FactoryDataChangeHandler;
import com.google.gwt.it2tool.client.FactorySorter.SortedBy;
import com.google.gwt.it2tool.client.Production;
import com.google.gwt.it2tool.client.ProductionPrototype;
import com.google.gwt.it2tool.client.widget.FactoryLabel.IFactoryClickedHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SuggestOracle;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
import com.google.gwt.user.client.ui.TextBox;

public class FactoryFlexTable extends ProductFlexTable implements FactoryDataChangeHandler {
	
	//TABLE ROWS
	private final int COL_ID=0;
	private final int COL_CUSTOM_ORDER=1;
	private final int COL_FACTORY_NAME=2;
	private final int COL_PRODUCT_NAME=3;
	private final int COL_PRODUCT_AREA=4;
	private final int COL_PRODUCT_MINUTES=5;
	private final int COL_PRODUCT_DURATION=6;
	private final int COL_PRODUCT_PRODUCTIVITY=7;
	private final int COL_PRODUCT_OUTPUT=8;
	private final int COL_REMOVE=9;
	
	private ArrayList<IFactoryEventsHandler> eventHandlers = new ArrayList<FactoryFlexTable.IFactoryEventsHandler>();
	
	//Underlying DataSet
	private FactorySorter sorter;
	
	private CustomFactoryOrder customFactoryOrder;
	
	private final Button collapse = new Button("<<");
	private final Button expand = new Button(">>");
	private boolean isVerticallyCollapsed;
	private boolean displayCustomOrderCol = false;
	private boolean isFactoryDetailPanel = false;
	
	public FactoryFlexTable(Factory f){
		super();
		sorter=null;
		isVerticallyCollapsed = true;
		isFactoryDetailPanel = true;
		initTableHeader();
		displayFactory(f);
	}
	
	public FactoryFlexTable(boolean isVerticallyCollapsed){
		super();
		this.isVerticallyCollapsed = isVerticallyCollapsed;
		sorter = new FactorySorter(this);
		initTableHeader();
	}

	private void initTableHeader() {
		setText(0, COL_ID, "ID");
	    getCellFormatter().addStyleName(0, COL_ID,"idCol");
	    setText(0, COL_CUSTOM_ORDER, "Reihenfolge");
	    if (!displayCustomOrderCol){
			getCellFormatter().addStyleName(0, COL_CUSTOM_ORDER,"idCol");
		}
	  
	    if(!isFactoryDetailPanel){
	    	setWidget(0, COL_FACTORY_NAME, getFactoryNameLabel());
	    }else{
	    	getCellFormatter().addStyleName(0, COL_FACTORY_NAME,"idCol");
	    }
		setText(0, COL_PRODUCT_NAME, "Produkt");
		setWidget(0, COL_PRODUCT_AREA, getAreaLabel());
		setText(0, COL_PRODUCT_MINUTES, "Minuten");
		if(!isVerticallyCollapsed){
			setWidget(0, COL_PRODUCT_DURATION, getDurationLabel());
			setText(0, COL_PRODUCT_PRODUCTIVITY, "Ergiebigkeit");
		}
		setWidget(0, getOutputCol(), getOutputLabel());
		
		if(!isFactoryDetailPanel){
			initExpandCollapseVerticallyButton();
			if(!isVerticallyCollapsed){
				setWidget(0, getRemoveCol(), collapse);
			}else{
				setWidget(0, getRemoveCol(), expand);
			}
		}
		
		// Add styles to elements
		setCellPadding(6);
		getRowFormatter().addStyleName(0, "factoryListHeader");
		addStyleName("factoryList");
		formatCellsOfRow(0);
		getCellFormatter().addStyleName(0, getRemoveCol(), "factoryListRemoveColumn");
		getColumnFormatter().addStyleName(COL_ID, "idCol");
		if (!displayCustomOrderCol){
			getColumnFormatter().addStyleName(COL_CUSTOM_ORDER, "idCol");
		}else{
			getColumnFormatter().addStyleName(COL_CUSTOM_ORDER, "orderTextBox");
		}
	}

	private Label getFactoryNameLabel(){
		final Label factoryName = new Label("Fabrikname");
		factoryName.addStyleName("clickableLabel");
		factoryName.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				if (sorter.getSortedBy() != SortedBy.NAME_ASC){
					sorter.sortByNameAsc();
					factoryName.setText("Fabrikname ↑");
				}else{
					sorter.sortByNameDesc();
					factoryName.setText("Fabrikname ↓");
				}								
			}
		});
		return factoryName;
	}
	
	private Label getDurationLabel(){
		Label l = new Label("Dauer");
		l.setTitle("bei 100m²");
		return l;
	}
	
	private Label getOutputLabel(){
		Label l = new Label("Produktion");
		l.setTitle("in 24h");
		return l;
	}
	
	private Label getAreaLabel(){
		Label l = new Label("Fläche");
		l.setTitle("der Produktion. In m²");
		return l;
	}
	
	public void addIFactoryEventHandler(IFactoryEventsHandler handler){
		eventHandlers.add(handler);
	}
	
	public void removeIFactoryEventHandler(IFactoryEventsHandler handler){
		if(handler!=null && eventHandlers.contains(handler)){
			eventHandlers.remove(handler);
		}
	}
	
	private void triggerOnError(String error){
		for(IFactoryEventsHandler handler: eventHandlers){
			handler.onError(error);
		}
	}
	
	private void triggerOnFactoryClicked(Factory factory, ClickEvent event){
		for(IFactoryEventsHandler handler: eventHandlers){
			handler.onFactoryClicked(factory,event);
		}
	}
	
	private void triggerOnFactoryChanged(Factory factory){
		for(IFactoryEventsHandler handler: eventHandlers){
			handler.onFactoryChanged(factory);
		}
	}
	
	private void triggerOnFactoryRemoved(Factory factory){
		for(IFactoryEventsHandler handler: eventHandlers){
			handler.onFactoryRemoved(factory);
		}
	}
	
	private void triggerOnProductionChanged(Production prod){
		for(IFactoryEventsHandler handler: eventHandlers){
			handler.onProductionChanged(prod);
		}
	}
	
	private void triggerOnProductionRemoved(Factory factory, Production prod){
		for(IFactoryEventsHandler handler: eventHandlers){
			handler.onProductionRemoved(factory, prod);
		}
	}
	
	private void triggerOnTableCollapsed(boolean collapsed){
		for(IFactoryEventsHandler handler: eventHandlers){
			handler.onTableCollapse(collapsed);
		}
	}

	private void formatCellsOfRow(int row) {
		getCellFormatter().addStyleName(row, COL_FACTORY_NAME, "factoryListTextColumn");
		getCellFormatter().addStyleName(row, COL_PRODUCT_NAME, "factoryListTextColumn");
		getCellFormatter().addStyleName(row, COL_PRODUCT_AREA, "factoryListNumericColumn");
		getCellFormatter().addStyleName(row, COL_PRODUCT_MINUTES, "factoryListNumericColumn");
		getCellFormatter().addStyleName(row, COL_PRODUCT_MINUTES, "minutesWidget");
		if(!isVerticallyCollapsed){
			getCellFormatter().addStyleName(row, COL_PRODUCT_DURATION, "factoryListNumericColumn");
			getCellFormatter().addStyleName(row, COL_PRODUCT_PRODUCTIVITY, "factoryListNumericColumn");
		}
		if(displayCustomOrderCol){
			getCellFormatter().addStyleName(row, COL_CUSTOM_ORDER, "orderTextBox");
		}
		getCellFormatter().addStyleName(row, getOutputCol(), "factoryListNumericColumn");
	}
	
	public void addFactory(String name) {		
		// Don't add the Factory if it's already in the table.
		if (factoryNameAlreadyExists(name)){
			triggerOnError("Fabrik existiert bereits!");
			return;
		}
		if (name.length()==0) {
			triggerOnError("Der Fabrikname muss aus mindestens einem Zeichen bestehen");
			return;
		}
		
		final Factory newFactory = new Factory(name);
		displayFactory(newFactory);
	  }
	
	private void displayFactory(final Factory newFactory){
		// Add the Factory to the table.
		int row = getRowCount();
		final String id = newFactory.getId();
		if (!isFactoryDetailPanel){
			setText(row, COL_ID, id);
			getCellFormatter().addStyleName(row, COL_ID,"idCol");		
			getCellFormatter().addStyleName(row, getRemoveCol(), "factoryListRemoveColumn");

			FactoryLabel factoryLabel = new FactoryLabel(newFactory);
			factoryLabel.addFactoryClickedHandler(new IFactoryClickedHandler() {			
				@Override
				public void onFactoryClicked(Factory factory, ClickEvent event) {
					triggerOnFactoryClicked(newFactory, event);				
				}
			});

			setWidget(row, COL_FACTORY_NAME, factoryLabel);


			//Display CustomOrder
			if(displayCustomOrderCol){
				customFactoryOrder = dataCache.getCustomFactoryOrder();			
				int pos = customFactoryOrder.getPositionForFactory(newFactory);
				if(pos==0) {
					pos = row;
					customFactoryOrder.setFactoryPosition(newFactory, row);
				}

				final TextBox orderBox = new TextBox();
				orderBox.setText(Integer.toString(pos));
				orderBox.addChangeHandler(new ChangeHandler() {				
					@Override
					public void onChange(ChangeEvent event) {
						customFactoryOrder.setFactoryPosition(newFactory, Integer.parseInt(orderBox.getText()));					
					}
				});

				getCellFormatter().addStyleName(row, COL_CUSTOM_ORDER,"orderCell");			
				orderBox.addStyleName("orderTextBox");
				setWidget(row, COL_CUSTOM_ORDER, orderBox);
			}else{
				getCellFormatter().addStyleName(row, COL_CUSTOM_ORDER,"idCol");
			}

			// Add a button to remove this Factory from the table.
			Button removeFactoryButton = new Button("x");
			removeFactoryButton.addStyleDependentName("remove");
			removeFactoryButton.addClickHandler(new ClickHandler() {
				public void onClick(ClickEvent event) {
					triggerOnFactoryRemoved(newFactory);
					undisplayFactory(newFactory);
				}
			});
			setWidget(row, getRemoveCol(), removeFactoryButton);


			final Button expandAddProductionButton = new Button("+");
			final Button collapseAddProductionButton = new Button("-");;

			expandAddProductionButton.addStyleDependentName("expandCollapse");
			expandAddProductionButton.addClickHandler(new ClickHandler() {
				public void onClick(ClickEvent event) {
					if (isVerticallyCollapsed){
						verticallyExpand();
					}else{
						showAddProductionRow(newFactory);
						setWidget(getRowForId(newFactory.getId()), COL_PRODUCT_NAME, collapseAddProductionButton);
					}
				}
			});

			collapseAddProductionButton.addStyleDependentName("expandCollapse");
			collapseAddProductionButton.addClickHandler(new ClickHandler() {
				public void onClick(ClickEvent event) {
					hideAddProductionRow(newFactory);
					setWidget(getRowForId(newFactory.getId()), COL_PRODUCT_NAME, expandAddProductionButton);
				}
			});


			setWidget(row, COL_PRODUCT_NAME, expandAddProductionButton);
			
			addAddProductRow(newFactory, row+1);
		}else{
			addAddProductRow(newFactory, row);
		}
		
		
		
		ArrayList<Production> productions = newFactory.getProductions();
		if(!productions.isEmpty()){
			int size=productions.size();
			for (int i=0;i<size;i++){
				row++;
				addProductionRow(row,newFactory, productions.get(i));				
			}
		}
	}
	
	private void undisplayFactory(Factory fac){
		int row = getRowForId(fac.getId());
		removeRow(row);
		
		for (int i=0; i<fac.getProductionsCount();i++){
			removeRow(row); //SomeProductionRow
		}
		removeRow(row); //addProductionRow
	}
	
	private void addAddProductRow(final Factory factory, int row){
		final ProductSuggestBox product = new ProductSuggestBox();
		final TextBox area = new TextBox();
		final TextBox duration = new TextBox();
		final TextBox productivity = new TextBox();
		
		product.addKeyUpHandler(new KeyUpHandler() {
			public void onKeyUp(KeyUpEvent event) {			  
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { //KEY_ENTER does not work
					area.setFocus(true);
				}
			}
		});
		product.addSelectionHandler(new SelectionHandler<SuggestOracle.Suggestion>() {			
			@Override
			public void onSelection(SelectionEvent<Suggestion> event) {
				ProductionPrototype p = dataCache.getPrototypes().get(product.getText());
				if(p!=null){					
					duration.setText(Double.toString(p.getDuration()));
					productivity.setText(Double.toString(p.getProductivity()));
				}
				
			}
		});
		area.addStyleName("factoryListNumericColumn");
		area.addKeyUpHandler(new KeyUpHandler() {
			public void onKeyUp(KeyUpEvent event) {			  
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { //KEY_ENTER does not work
					duration.setFocus(true);
				}
			}
		});
		duration.addStyleName("factoryListNumericColumn");
		duration.addKeyUpHandler(new KeyUpHandler() {
			public void onKeyUp(KeyUpEvent event) {			  
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { //KEY_ENTER does not work
					productivity.setFocus(true);
				}
			}
		});
		productivity.addStyleName("factoryListNumericColumn");
		productivity.addKeyUpHandler(new KeyUpHandler() {
			public void onKeyUp(KeyUpEvent event) {			  
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { //KEY_ENTER does not work
					addProduction(factory);
				}
			}
		});
		//factoriesFlexTable.insertRow(row+1);
		insertRow(row);
		getCellFormatter().addStyleName(row, COL_ID,"idCol");
		if (!displayCustomOrderCol){
			getCellFormatter().addStyleName(row, COL_CUSTOM_ORDER,"idCol");
		}
		if(isFactoryDetailPanel){
			getCellFormatter().addStyleName(row, COL_FACTORY_NAME,"idCol");
		}
		setWidget(row, COL_PRODUCT_NAME, product);
		setWidget(row, COL_PRODUCT_AREA, area);
		if(!isVerticallyCollapsed){
			setWidget(row, COL_PRODUCT_DURATION, duration);
			setWidget(row, COL_PRODUCT_PRODUCTIVITY, productivity);
		}
		Button addProductButton = new Button("Produkt hinzufügen");
		
		addProductButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				addProduction(factory);
			}
		});
		setWidget(row, getOutputCol(), addProductButton);
		
		formatCellsOfRow(row);
		
		getRowFormatter().setVisible(row, false);
	}
	
	/**
	 * Adds a new Production
	 * 
	 * @param row to read input values from
	 */
	private void addProduction(Factory factory){
		int row = getRowForId(factory.getId());
		
		//To trigger change of Expand to 
		Button xButton = (Button)getWidget(row, COL_PRODUCT_NAME);
		if(xButton.getText().equals("-")){
			//If minus we want te expand button to be shown
			xButton.click();
		}
		
		if (!isCellPresent(row, COL_PRODUCT_NAME) || 
				!isCellPresent(row, COL_PRODUCT_AREA) || 
				!isCellPresent(row, COL_PRODUCT_DURATION)|| 
				!isCellPresent(row, COL_PRODUCT_PRODUCTIVITY)){
			triggerOnError("Unvollständige Tabelle!");
			return;
		}
		
		row = getLastRowOfFactory(factory.getId());
		String name = ((ProductSuggestBox)getWidget(row, COL_PRODUCT_NAME)).getText().trim();
		
		if (name.length()==0) {
			triggerOnError("Der Produktname muss aus mindestens einem Zeichen bestehen!");
			return;
		}
		
		if (productNameAlreadyExists(factory,name)){
			triggerOnError("Produkt existiert bereits in dieser Fabrik!");
			return;
		}
		
		
				
		Production newProduction =  new Production();
		newProduction.generateId();
		
		try{
			newProduction.setName(name);
			newProduction.setArea(Integer.parseInt(((TextBox)getWidget(row, COL_PRODUCT_AREA)).getText().trim()));
			newProduction.setDuration(Integer.parseInt(((TextBox)getWidget(row, COL_PRODUCT_DURATION)).getText().trim()));
			newProduction.setProductivity(Integer.parseInt(((TextBox)getWidget(row, COL_PRODUCT_PRODUCTIVITY)).getText().trim()));
		}catch (ClassCastException e){
			triggerOnError(e.getMessage());
			return;
		}catch (IndexOutOfBoundsException ex){
			triggerOnError("Eingabefeld nicht gefunden!");
			return;
		}catch (NumberFormatException exe){
			triggerOnError(exe.getMessage());
			return;
		}		
		
		factory.addProduction(newProduction);
		triggerOnFactoryChanged(factory);
		
		addProductionRow(row, factory, newProduction);
		
	}
	
	private void addProductionRow(final int row, final Factory factory,final Production production){		
		if(!isFactoryDetailPanel){
			removeRow(row);	
			insertRow(row);
		}else{
			insertRow(row);
			getCellFormatter().addStyleName(row, COL_FACTORY_NAME,"idCol");
		}
		
		setText(row, COL_ID, production.getId());
		getCellFormatter().addStyleName(row, COL_ID,"idCol");
		if (!displayCustomOrderCol){
			getCellFormatter().addStyleName(row, COL_CUSTOM_ORDER,"idCol");
		}
		if(!isVerticallyCollapsed){
			setText(row, COL_PRODUCT_DURATION, Integer.toString((int)production.getDuration()));
			setText(row, COL_PRODUCT_PRODUCTIVITY, Integer.toString((int)production.getProductivity()));
		}
		setText(row, getOutputCol(), Integer.toString(production.getOutput()));	
		
		setWidget(row, COL_PRODUCT_NAME, getProductLabel(production));
		setWidget(row, COL_PRODUCT_AREA, getAreaLabel(factory,production));	
		setWidget(row, COL_PRODUCT_MINUTES, new MinuteWidget(production));

		// Add a button to remove this Production from the table.
		Button removeButton = new Button("x");
		removeButton.addStyleDependentName("remove");
		removeButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				triggerOnProductionRemoved(factory, production);
				factory.removeProduction(production);
				undisplayProduction(production);
			}
		});
		setWidget(row, getRemoveCol(), removeButton);
		
		formatCellsOfRow(row);
		getCellFormatter().addStyleName(row, getOutputCol(), "productionOutput");		
		
		addAddProductRow(factory,row+1);
	}
	
	private TextBox getAreaTextBox(final Factory factory,final Production production){
		final TextBox area = new TextBox();
		area.setText(Integer.toString((int)production.getArea()));
		area.addStyleName("factoryListNumericColumn");
		
		area.addChangeHandler(new ChangeHandler() {			
			public void onChange(ChangeEvent event) {
				persistAreaChange(factory,production);
				setWidget(getRowForId(production.getId()), COL_PRODUCT_AREA, getAreaLabel(factory,production));
			}
		});
		
		area.addBlurHandler(new BlurHandler() {
			//Call when the widget loses focus
			@Override
			public void onBlur(BlurEvent event) {
				persistAreaChange(factory,production);
				setWidget(getRowForId(production.getId()), COL_PRODUCT_AREA, getAreaLabel(factory,production));
				
			}
		});
		
		area.addKeyUpHandler(new KeyUpHandler() {
			public void onKeyUp(KeyUpEvent event) {			  
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER || event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
					persistAreaChange(factory,production);
					setWidget(getRowForId(production.getId()), COL_PRODUCT_AREA, getAreaLabel(factory,production));
				}
			}
		});
		
		return area;
	}
	
	private void persistAreaChange(Factory factory, Production production){
		int row = getRowForId(production.getId());
		if (getWidget(row, COL_PRODUCT_AREA)!=null){
			String newArea = ((TextBox) getWidget(row, COL_PRODUCT_AREA)).getText();
			double area =production.getArea();
			try{
				area = Double.parseDouble(newArea);
			}catch (NumberFormatException e){
				triggerOnError("Fehler beim einlesen der Flächenzahl!");
				return;
			}
			
			if (production.getArea()!=area){
				production.setArea(area);
				triggerOnProductionChanged(production);
				setText(row, getOutputCol(), Integer.toString(production.getOutput()));
			}	
		}
	}
	
	private Label getAreaLabel(final Factory factory,final Production production){
		final Label area = new Label();
		area.setText(Integer.toString((int)production.getArea())+ " m²");
		area.addStyleName("factoryListNumericColumn");
		area.addStyleName("clickableLabel");
		
		area.addClickHandler(new ClickHandler() {			
			public void onClick(ClickEvent event) {
				TextBox area = getAreaTextBox(factory,production);
				setWidget(getRowForId(production.getId()), COL_PRODUCT_AREA, area);
				area.setFocus(true);
			}
		});
		return area; 
	}
	
	private void initExpandCollapseVerticallyButton(){
		
		collapse.addStyleName("remove");
		collapse.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				verticallyCollapse();			
			}
		});
		
		expand.addStyleName("remove");
		expand.addClickHandler(new ClickHandler() {					
			@Override
			public void onClick(ClickEvent event) {
				verticallyExpand();
			}
		});
	}
	
	private void verticallyCollapse(){
		triggerOnTableCollapsed(true);
	}
	
	private void verticallyExpand(){
		triggerOnTableCollapsed(false);
	}
	
	private void showAddProductionRow(final Factory factory){				
			setAddProdcutionRowVisible(factory, true);		
	}
	
	private void hideAddProductionRow(Factory factory){
		setAddProdcutionRowVisible(factory, false);
	}
	
	private void setAddProdcutionRowVisible(Factory factory,boolean visible){
		int row = getLastRowOfFactory(factory.getId());
		getRowFormatter().setVisible(row, visible);
	}
	
	private int getLastRowOfFactory(String id){
		int row = getRowForId(id);
		if (row>0){
			int size = getRowCount();
			for (int i=row+1;i<size;i++){
				if (!getText(i, COL_FACTORY_NAME).equals("")){
					return i-1;
				}
			}
			return size-1; //We assume this was the last factory
		}else{
			return -1;
		}
	}
	
	private void undisplayProduction(Production prod){
		String id = prod.getId();
		int row = getRowForId(id);
		if (row != -1){		
			removeRow(row);;
		}
	}	

	private boolean factoryNameAlreadyExists(String name){
		Iterator<Factory> iter = sorter.getFactories().iterator();
		while(iter.hasNext()){
			if (iter.next().getName().equals(name)){
				return true;
			}
		}
		return false;
	}
	
	private boolean productNameAlreadyExists(Factory fac, String name){
		Iterator<Production> iter = fac.getProductions().iterator();
		while(iter.hasNext()){
			if (iter.next().getName().equals(name)){
				return true;
			}
		}
		return false;
	}
	
	private int getRowForId(String id){
		int size = getRowCount();
		//Start at row 1 as row 0 is header
		for (int i=1;i<size;i++){
			if (getText(i, COL_ID).equals(id)){
				return i;
			}
		}
		return -1;
	}
	
	private int getOutputCol(){
		if(!isVerticallyCollapsed){
			return COL_PRODUCT_OUTPUT;
		}else{
			return COL_PRODUCT_OUTPUT-2;
		}
	}
	
	private int getRemoveCol(){
		if(!isVerticallyCollapsed){
			return COL_REMOVE;
		}else{
			return COL_REMOVE-2;
		}
	}
	
	private void reDrawTable(){
		TreeSet<Factory> result = sorter.getFactories();
		if(result!=null){
			int size = getRowCount();
			for (int i=0;i<size;i++){
				removeRow(0);
			}

			initTableHeader();
			for (Factory fac : result) {
				displayFactory(fac);
			}
		}
	}
	
	public void setVerticallyCollapsed(boolean collapse){
		isVerticallyCollapsed = collapse;
		reDrawTable();
	}
	
	public void onShowCustomOrder(){
		displayCustomOrderCol = true;
		reDrawTable();
	}
	
	public void onHideAndSaveCustomOrder(){
		displayCustomOrderCol = false;
		dataCache.setCustomFactoryOrder(customFactoryOrder);
		sortByCustom();
	}
	
	public void sortByCustom(){
		sorter.sortByCustom();
	}
	
	public interface IFactoryEventsHandler{
		public void onError(String error);
		public void onFactoryClicked(Factory factory, ClickEvent event);
		public void onFactoryChanged(Factory factory);
		public void onFactoryRemoved(Factory factory);
		public void onProductionChanged(Production prod);
		public void onProductionRemoved(Factory factory, Production prod);
		public void onTableCollapse(boolean collapsed);
	}

	@Override
	public void onFactoryDataChanged() {
		reDrawTable();		
	}
}
